package com.gitee.wsl.doc.prosemirror.transform.internal
//
//import com.gitee.wsl.doc.prosemirror.exception.RangeError
//import com.gitee.wsl.doc.prosemirror.model.attr.Attrs
//import com.gitee.wsl.doc.prosemirror.model.fragment.Fragment
//import com.gitee.wsl.doc.prosemirror.model.mark.Mark
//import com.gitee.wsl.doc.prosemirror.model.node.Node
//import com.gitee.wsl.doc.prosemirror.model.node.NodeBase
//import com.gitee.wsl.doc.prosemirror.model.content.NodeRange
//import com.gitee.wsl.doc.prosemirror.model.Whitespace
//import com.gitee.wsl.doc.prosemirror.model.fragment.Slice
//import com.gitee.wsl.doc.prosemirror.model.node.NodeType
//import com.gitee.wsl.doc.prosemirror.model.node.ext.canChangeType
//import com.gitee.wsl.doc.prosemirror.model.node.ext.resolveSafe
//import com.gitee.wsl.doc.prosemirror.transform.Transform
//import com.gitee.wsl.doc.prosemirror.transform.step.ReplaceAroundStep
//import com.gitee.wsl.doc.prosemirror.transform.step.ReplaceStep
//import com.gitee.wsl.doc.prosemirror.util.verbose
//
//
//
//internal fun lift(tr: Transform, range: NodeRange, target: Int) {
//    val from = range.from
//    val to = range.to
//    val depth = range.depth
//
//    val gapStart = from.before(depth + 1)
//    val gapEnd = to.after(depth + 1)
//    var start = gapStart
//    var end = gapEnd
//
//    var before = Fragment.empty
//    var openStart = 0
//    var splitting = false
//    for (d in depth downTo target + 1) {
//        if (splitting || from.index(d) > 0) {
//            splitting = true
//            before = Fragment.from(from.node(d).copy(before))
//            openStart++
//        } else {
//            start--
//        }
//    }
//    var after = Fragment.empty
//    var openEnd = 0
//    splitting = false
//    for (d in depth downTo target + 1) {
//        if (splitting || to.after(d + 1) < to.end(d)) {
//            splitting = true
//            after = Fragment.from(to.node(d).copy(after))
//            openEnd++
//        } else {
//            end++
//        }
//    }
//
//    tr.step(
//        ReplaceAroundStep(
//            from = start,
//            to = end,
//            gapFrom = gapStart,
//            gapTo = gapEnd,
//            slice = Slice(before.append(after), openStart, openEnd),
//            insert = before.size - openStart,
//            structure = true
//        )
//    )
//}
//
//
//internal fun wrap(tr: Transform, range: NodeRange, wrappers: List<NodeBase>) {
//    var content = Fragment.empty
//    for (i in wrappers.size - 1 downTo 0) {
//        if (content.size != 0) {
//            val match = wrappers[i].type.contentMatch.matchFragment(content)
//            if (match == null || !match.validEnd) {
//                throw RangeError(
//                    "Wrapper type given to Transform.wrap does not form valid content of its parent wrapper"
//                )
//            }
//        }
//        content = Fragment.from(wrappers[i].type.create(wrappers[i].attrs, content))
//    }
//
//    val start = range.start
//    val end = range.end
//    tr.step(ReplaceAroundStep(start, end, start, end, Slice(content, 0, 0), wrappers.size, true))
//}
//
//internal fun setBlockType(tr: Transform, from: Int, to: Int, type: NodeType, attrs: Attrs?) =
//    setBlockType(tr, from, to, type, { attrs })
//
//internal fun setBlockType(tr: Transform, from: Int, to: Int, type: NodeType, attrs: (Node) -> Attrs?) {
//    if (!type.isTextblock) throw RangeError("Type given to setBlockType should be a textblock")
//    val mapFrom = tr.steps.size
//    tr.doc.nodesBetween(from, to) { node, pos, parent, index ->
//        val attrsHere = attrs(node)
//        if (
//            node.isTextblock &&
//            !node.hasMarkup(type, attrsHere) &&
//            tr.doc.canChangeType(tr.mapping.slice(mapFrom).map(pos), type)
//        ) {
//            var convertNewlines: Boolean? = null
//            if (type.schema.linebreakReplacement != null) {
//                val pre = type.whitespace == Whitespace.PRE
//                val supportLinebreak = type.schema.linebreakReplacement?.let { type.contentMatch.matchType(it) } != null
//                if (pre && !supportLinebreak) {
//                    convertNewlines = false
//                } else if (!pre && supportLinebreak) {
//                    convertNewlines = true
//                }
//            }
//
//            // Ensure all markup that isn't allowed in the new node type is cleared
//            if (convertNewlines != null && !convertNewlines) replaceLineBreaks(tr, node, pos, mapFrom)
//            clearIncompatible(tr, tr.mapping.slice(mapFrom).map(pos, 1), type, null, convertNewlines === null)
//            val mapping = tr.mapping.slice(mapFrom)
//            val startM = mapping.map(pos, 1)
//            val endM = mapping.map(pos + node.nodeSize, 1)
//            tr.step(
//                ReplaceAroundStep(
//                    from = startM,
//                    to = endM,
//                    gapFrom = startM + 1,
//                    gapTo = endM - 1,
//                    slice = Slice(Fragment.from(type.create(attrsHere, null as Fragment?, node.marks)), 0, 0),
//                    insert = 1,
//                    structure = true
//                )
//            )
//            if (convertNewlines == true) replaceNewlines(tr, node, pos, mapFrom)
//            false
//        } else {
//            true
//        }
//    }
//}
//
//internal fun replaceNewlines(tr: Transform, node: Node, pos: Int, mapFrom: Int) {
//    node.forEach { child, offset, _ ->
//        if (child.isText) {
//            val newline = Regex("\r?\n|\r")
//            val text = child.text ?: ""
//            newline.findAll(text).forEach {
//                val start = tr.mapping.slice(mapFrom).map(pos + 1 + offset + it.range.first)
//                tr.replaceWith(start, start + 1, node.type.schema.linebreakReplacement!!.create())
//            }
//        }
//    }
//}
//
//internal fun replaceLineBreaks(tr: Transform, node: Node, pos: Int, mapFrom: Int) {
//    node.forEach { child, offset, _ ->
//        if (child.type == child.type.schema.linebreakReplacement) {
//            val start = tr.mapping.slice(mapFrom).map(pos + 1 + offset)
//            tr.replaceWith(start, start + 1, node.type.schema.text("\n"))
//        }
//    }
//}
//
//
//
//// Change the type, attributes, and/or marks of the node at `pos`. When `type` isn't given, the
//// existing node type is preserved,
//internal fun setNodeMarkup(tr: Transform, pos: Int, type: NodeType?, attrs: Attrs?, marks: List<Mark>?): Transform {
//    val node = tr.doc.nodeAt(pos) ?: throw RangeError("No node at given position")
//    val thisType = type ?: node.type
//    val newNode = thisType.create(attrs, null as Fragment?, marks ?: node.marks)
//    if (node.isLeaf) {
//        return tr.replaceWith(pos, pos + node.nodeSize, newNode)
//    }
//
//    if (!thisType.validContent(node.content)) {
//        throw RangeError(
//            if (verbose) {
//                "Invalid content for node type ${thisType.name}: ${node.content}"
//            } else {
//                "Invalid content for node type ${thisType.name}"
//            }
//        )
//    }
//
//    return tr.step(
//        ReplaceAroundStep(
//            pos,
//            pos + node.nodeSize,
//            pos + 1,
//            pos + node.nodeSize - 1,
//            Slice(Fragment.from(newNode), 0, 0),
//            1,
//            true
//        )
//    )
//}
//
//internal fun split(tr: Transform, pos: Int, depth: Int = 1, typesAfter: List<NodeBase?>?): Transform {
//    val thisPos = tr.doc.resolveSafe(pos) ?: return tr
//    var before = Fragment.empty
//    var after = Fragment.empty
//    var d = thisPos.depth
//    val e = thisPos.depth - depth
//    var i = depth - 1
//    while (d > e) {
//        before = Fragment.from(thisPos.node(d).copy(before))
//        val typeAfter = typesAfter?.get(i)
//        after = Fragment.from(typeAfter?.type?.create(typeAfter.attrs, after) ?: thisPos.node(d).copy(after))
//        d--
//        i--
//    }
//    return tr.step(ReplaceStep(pos, pos, Slice(before.append(after), depth, depth), true))
//}
//
//
//internal fun join(tr: Transform, pos: Int, depth: Int): Transform {
//    var convertNewlines: Boolean? = null
//    val linebreakReplacement = tr.doc.type.schema.linebreakReplacement
//    val before = tr.doc.resolve(pos - depth)
//    val beforeType = before.node().type
//    if (linebreakReplacement != null && beforeType.inlineContent) {
//        val pre = beforeType.whitespace == Whitespace.PRE
//        val supportLinebreak = beforeType.contentMatch.matchType(linebreakReplacement) != null
//        if (pre && !supportLinebreak) {
//            convertNewlines = false
//        } else if (!pre && supportLinebreak) {
//            convertNewlines = true
//        }
//    }
//    val mapFrom = tr.steps.size
//    if (convertNewlines == false) {
//        val after = tr.doc.resolve(pos + depth)
//        replaceLineBreaks(tr, after.node(), after.before(), mapFrom)
//    }
//    if (beforeType.inlineContent) {
//        clearIncompatible(
//            tr,
//            pos + depth - 1,
//            beforeType,
//            before.node().contentMatchAt(before.index()),
//            convertNewlines == null
//        )
//    }
//    val mapping = tr.mapping.slice(mapFrom)
//    val start = mapping.map(pos - depth)
//    tr.step(
//        ReplaceStep(
//            start,
//            mapping.map(pos + depth, -1),
//            Slice.empty,
//            true
//        )
//    )
//    if (convertNewlines == true) {
//        val full = tr.doc.resolve(start)
//        replaceNewlines(tr, full.node(), full.before(), tr.steps.size)
//    }
//    return tr
//}


